package com.xxl.job.executor.sjbank.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.executor.sjbank.mapper.FiStopcallMapper;
import com.xxl.job.executor.sjbank.pojo.*;
import com.xxl.job.executor.sjbank.pojo.model.AiPushLf;
import com.xxl.job.executor.sjbank.pojo.model.AiPushMt;
import com.xxl.job.executor.sjbank.service.FiCreditcasesHistService;
import com.xxl.job.executor.sjbank.service.FiCreditcasesService;
import com.xxl.job.executor.sjbank.mapper.FiCreditcasesMapper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.xxl.job.executor.plugin.JPubUtils.*;


/**
 * @author tsu
 * @description 针对表【fi_creditcases】的数据库操作Service实现
 * @createDate 2024-03-11 16:06:08
 */
@Service
public class FiCreditcasesServiceImpl extends MPJBaseServiceImpl<FiCreditcasesMapper, FiCreditcases>
        implements FiCreditcasesService {

    @Resource
    FiCreditcasesMapper fiCreditcasesMapper;
    @Resource
    FiCreditcasesHistService fiCreditcasesHistService;
    @Resource
    FiStopcallMapper fiStopcallMapper;

    @Value("${aipush.url}")
    private String aiurl;

    @Override
    public void generateCase() {
        XxlJobHelper.log("XXL-JOB, generateCase:生成案件开始.");
        // 获取当前日期和时间
        LocalDateTime currentDateTime = LocalDateTime.now();
        String batchid = currentDateTime.format(DateTimeFormatter.ofPattern("yyMMddHHmmss"));
        List<LinkedHashMap> list = fiCreditcasesMapper.queryContract();

        XxlJobHelper.log("XXL-JOB, generateCase:最新T+1借据条数:" + list.size());

        list.forEach(row -> {
            try {
                FiCreditcases fiCreditcases = new FiCreditcases();
                fiCreditcases.setCreditcaseid(ObjectToInt(row.get("creditcaseid")));
                fiCreditcases.setCustomernumber(ObjectToString(row.get("custid")));
                fiCreditcases.setCollectno(ObjectToString(row.get("billid")));
                fiCreditcases.setCreditAcct(ObjectToString(row.get("contractid")));
                fiCreditcases.setLoanamt(ObjectToBigDecimal(row.get("loadamt")));
                fiCreditcases.setOdudPrin(ObjectToBigDecimal(row.get("overduetotal")));
                fiCreditcases.setOverPrin(ObjectToBigDecimal(row.get("overdueprin")));
                fiCreditcases.setInterestFee(ObjectToBigDecimal(row.get("overdueinte")));
                fiCreditcases.setPenchgAcc(ObjectToBigDecimal(row.get("overdueintp")));
                fiCreditcases.setOthExpense(ObjectToBigDecimal(row.get("fee")));
                fiCreditcases.setRepay(ObjectToBigDecimal(row.get("paymtclrd")));
                fiCreditcases.setRepayday(ObjectToString(row.get("repaydate")));
                fiCreditcases.setProdtype(ObjectToString(row.get("channelno")));
                fiCreditcases.setMthsOdue(ObjectToInt(row.get("mthsodue")));
                fiCreditcases.setMthsDay(ObjectToInt(row.get("mthsday")));
                fiCreditcases.setStatus(0);
                fiCreditcases.setStatusdt(new Date());
                fiCreditcases.setCcc("O");
                fiCreditcases.setBatchid(batchid);
                fiCreditcases.setMdusr("system");
                fiCreditcases.setMddt(new Date());
                fiCreditcases.setIndt(new Date());

                BigDecimal odudPrin = fiCreditcases.getOdudPrin();
                String collectno = fiCreditcases.getCollectno();
                FiCreditcases fc_obj = fiCreditcasesMapper.selectOne(new QueryWrapper<FiCreditcases>()
                        .eq("collectno", collectno));

                if (fc_obj == null) {
                    if (odudPrin.compareTo(BigDecimal.ZERO) > 0) {
                        fiCreditcases.setCrusr("system");
                        fiCreditcases.setCrdt(new Date());
                        save(fiCreditcases);
                    } else {
                        XxlJobHelper.log("借据号{}的逾期金额为:{},此借据将不生成案件！", collectno, odudPrin);
                    }
                } else {
                    if (fc_obj.getStatus() == 9) {
                        updateById(fiCreditcases);
                    } else {
                        fiCreditcasesMapper.update(null, new UpdateWrapper<FiCreditcases>()
                                .lambda()
                                .eq(FiCreditcases::getCollectno, collectno)
                                .set(FiCreditcases::getLoanamt, ObjectToBigDecimal(row.get("loadamt")))
                                .set(FiCreditcases::getOdudPrin, ObjectToBigDecimal(row.get("overduetotal")))
                                .set(FiCreditcases::getOverPrin, ObjectToBigDecimal(row.get("overdueprin")))
                                .set(FiCreditcases::getInterestFee, ObjectToBigDecimal(row.get("overdueinte")))
                                .set(FiCreditcases::getPenchgAcc, ObjectToBigDecimal(row.get("overdueintp")))
                                .set(FiCreditcases::getOthExpense, ObjectToBigDecimal(row.get("fee")))
                                .set(FiCreditcases::getRepay, ObjectToBigDecimal(row.get("paymtclrd")))
                                .set(FiCreditcases::getRepayday, ObjectToString(row.get("repaydate")))
                                .set(FiCreditcases::getProdtype, ObjectToString(row.get("channelno")))
                                .set(FiCreditcases::getMthsOdue, ObjectToInt(row.get("mthsodue")))
                                .set(FiCreditcases::getMthsDay, ObjectToInt(row.get("mthsday"))));
                    }
                }
            } catch (Exception e) {
                XxlJobHelper.log("XXL-JOB-generateCase, 错误日志:" + e + ">>>>>【异常列】：" + row);
            }
        });
        XxlJobHelper.log("XXL-JOB, generateCase:生成案件结束.");
    }

    @Override
    public void recyclingCase() {
        List<FiCreditcases> list = list(new QueryWrapper<FiCreditcases>()
                .in("ccc", "Q", "S")
                .in("status", 1, 2)
                .le("bindenddt", LocalDateTime.now()));
        XxlJobHelper.log("XXL-JOB, recyclingCase.待回收案件" + list.size() + "条.");
        List<FiCreditcasesHist> histlist = new ArrayList<>();
        list.forEach(x -> {
            try {
                x.setStatus(3);
                x.setStatusdt(new Date());
                x.setCcc("O");
                x.setRecycleusr("system");
                x.setRecycledt(new Date());
                x.setRecycledsc("到期自动回收");
                x.setMdusr("system");
                x.setMddt(new Date());
                updateById(x);
                FiCreditcases fiCase = fiCreditcasesMapper.selectOne(new QueryWrapper<FiCreditcases>().eq("collectno", x.getCollectno()));
                FiCreditcasesHist fiCreditcasesHist = new FiCreditcasesHist();
                // 将属性复制到新对象中
                BeanUtils.copyProperties(fiCase, fiCreditcasesHist);
                histlist.add(fiCreditcasesHist);
                baseMapper.update(null, new UpdateWrapper<FiCreditcases>()
                        .lambda()
                        .eq(FiCreditcases::getCreditcaseid, x.getCreditcaseid())
                        .set(FiCreditcases::getSendtousr, null)
                        .set(FiCreditcases::getAppointdt, null)
                        .set(FiCreditcases::getAssignbatchid, null)
                        .set(FiCreditcases::getAssignid, null)
                        .set(FiCreditcases::getAssigntype, null)
                        .set(FiCreditcases::getAssignusr, null)
                        .set(FiCreditcases::getAssigndt, null)
                        .set(FiCreditcases::getSendtodept, null)
                        .set(FiCreditcases::getBindenddt, null)
                        .set(FiCreditcases::getDistusr, null)
                        .set(FiCreditcases::getDistdt, null)
                        .set(FiCreditcases::getDistbatchid, null)
                        .set(FiCreditcases::getDistributetype, null)
                        .set(FiCreditcases::getDistributorid, null)
                        .set(FiCreditcases::getLastccdt, null)
                        .set(FiCreditcases::getLastcctaskid, null)
                );
            } catch (Exception e) {
                XxlJobHelper.log("XXL-JOB-recyclingCase, 错误日志:" + e + ">>>>>【异常列】：" + x);
            }
        });
        fiCreditcasesHistService.saveBatch(histlist);
    }

    private BigDecimal getPayAmount(String acctno, Date distDt) {//取实际还款额
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            //开始时间从分案次日凌晨开始，在函数里面计算
            String distdt = sdf.format(distDt);
            String recydt = sdf.format(new Date());
            XxlJobHelper.log("参数：{} -->> {} -->> {}", acctno, distdt, recydt);
            return fiStopcallMapper.getPayAmount(acctno, distdt, recydt);
        } catch (Exception e) {
            //e.printStackTrace();
            XxlJobHelper.log("getPayAmount, 错误日志：", e);
            return new BigDecimal(0.0);
        }
    }

    @Override
    public void aiPush() {
        // 个人｜乐分
        ySlf();

        // 美团｜车贷
        mTcd();
    }

    private void ySlf() {
        MPJLambdaWrapper<FiCreditcases> mpjLambdaWrapperGr = new MPJLambdaWrapper<>();
        mpjLambdaWrapperGr.leftJoin(CreditAccount.class, "c", CreditAccount::getAcct, FiCreditcases::getCreditAcct);
        mpjLambdaWrapperGr.leftJoin(CreditAccountBalance.class, "cb", CreditAccountBalance::getAcct, FiCreditcases::getCreditAcct);
        mpjLambdaWrapperGr.leftJoin(ConCustomer.class, "ct", ConCustomer::getCustomernumber, FiCreditcases::getCustomernumber);
        mpjLambdaWrapperGr.select(CreditAccount::getAcctType, CreditAccount::getMobileNum, CreditAccount::getMthsOdue, CreditAccount::getBillDate);
        mpjLambdaWrapperGr.select(CreditAccountBalance::getAge1Age6, CreditAccountBalance::getLowestRepayBal, CreditAccountBalance::getPaymtClrd, CreditAccountBalance::getSettledBillAmt, CreditAccountBalance::getSettledBillInt, CreditAccountBalance::getSettledBillFee, CreditAccountBalance::getSettledBillPrin, CreditAccountBalance::getStmBalnce);
        mpjLambdaWrapperGr.select(ConCustomer::getCustname, ConCustomer::getGender, ConCustomer::getCustomernumber, ConCustomer::getIsurgecust);
        mpjLambdaWrapperGr.selectAs("SELECT concat(to_char(now(),'YYYYMMDDHH24MISS'),(1000 + floor(random() * 9000)::int))", AiPushLf::getDataId);
        mpjLambdaWrapperGr.selectAs("(select cd.card_no from credit_card cd where cd.acct=t.credit_acct LIMIT 1)", AiPushLf::getCardNo);
        mpjLambdaWrapperGr.selectAs("to_char(c.open_dt,'YYYY-MM-DD')", AiPushLf::getOpenDt);
        mpjLambdaWrapperGr.selectAs("fc_getbillmonth(cd.bill_date)", AiPushLf::getBillMonth);
        mpjLambdaWrapperGr.selectAs("to_char(t.crdt,'YYYYMMDD')", AiPushLf::getDataDt);
        //mpjLambdaWrapperGr.selectAs("(select case tt.bill_date when tt.bill_date >= DATE_FORMAT(CURDATE(),'%m') then DATE_FORMAT(CURDATE(),'%m') else DATE_FORMAT(CURDATE(),'%m')-1 end from credit_account tt where tt.acct=t.credit_acct)", AiPushLf::getBillMonth);
        //mpjLambdaWrapperGr.selectAs("(SELECT CASE WHEN tt.bill_date::integer >= EXTRACT(MONTH FROM CURRENT_DATE) THEN EXTRACT(MONTH FROM CURRENT_DATE) ELSE EXTRACT(MONTH FROM CURRENT_DATE)-1 END FROM credit_account tt where tt.acct=t.credit_acct)", AiPushLf::getBillMonth);
        mpjLambdaWrapperGr.selectAs("(select cab.unsettled_bill_amt+cab.settled_bill_amt+cab.unamort_prin from credit_account_balance cab where cab.acct=t.credit_acct)", AiPushLf::getOverBal);
        mpjLambdaWrapperGr.eq(CreditAccount::getAcctType, "10");
        mpjLambdaWrapperGr.eq(CreditAccount::getMthsOdue, 1);
        mpjLambdaWrapperGr.gt(CreditAccountBalance::getSettledBillAmt, 0);
        mpjLambdaWrapperGr.eq(ConCustomer::getIsurgecust, "0");


        List<AiPushLf> listGr = selectJoinList(AiPushLf.class, mpjLambdaWrapperGr);

        MPJLambdaWrapper<FiCreditcases> mpjLambdaWrapperLf = new MPJLambdaWrapper<>();
        mpjLambdaWrapperLf.leftJoin(CreditAccount.class, "c", CreditAccount::getAcct, FiCreditcases::getCreditAcct);
        mpjLambdaWrapperLf.leftJoin(CreditAccountBalance.class, "cb", CreditAccountBalance::getAcct, FiCreditcases::getCreditAcct);
        mpjLambdaWrapperLf.leftJoin(ConCustomer.class, "ct", ConCustomer::getCustomernumber, FiCreditcases::getCustomernumber);
        mpjLambdaWrapperLf.select(CreditAccount::getAcctType, CreditAccount::getMobileNum, CreditAccount::getMthsOdue, CreditAccount::getBillDate);
        mpjLambdaWrapperLf.select(CreditAccountBalance::getAge1Age6, CreditAccountBalance::getLowestRepayBal, CreditAccountBalance::getPaymtClrd, CreditAccountBalance::getSettledBillAmt, CreditAccountBalance::getSettledBillInt, CreditAccountBalance::getSettledBillFee, CreditAccountBalance::getSettledBillPrin, CreditAccountBalance::getStmBalnce);
        mpjLambdaWrapperLf.select(ConCustomer::getCustname, ConCustomer::getGender, ConCustomer::getCustomernumber, ConCustomer::getIsurgecust);
        mpjLambdaWrapperLf.selectAs("t.creditcaseid", AiPushLf::getDataId);
        mpjLambdaWrapperLf.selectAs("(select cd.card_no from credit_card cd where cd.acct=t.credit_acct LIMIT 1)", AiPushLf::getCardNo);
        mpjLambdaWrapperGr.selectAs("to_char(c.open_dt,'YYYY-MM-DD')", AiPushLf::getOpenDt);
        mpjLambdaWrapperGr.selectAs("fc_getbillmonth(cd.bill_date)", AiPushLf::getBillMonth);
        mpjLambdaWrapperGr.selectAs("to_char(t.crdt,'YYYYMMDD')", AiPushLf::getDataDt);
        //mpjLambdaWrapperLf.selectAs("(select case tt.bill_date when tt.bill_date >= DATE_FORMAT(CURDATE(),'%m') then DATE_FORMAT(CURDATE(),'%m') else DATE_FORMAT(CURDATE(),'%m')-1 end from credit_account tt where tt.acct=t.credit_acct)", AiPushLf::getBillMonth);
        //mpjLambdaWrapperLf.selectAs("(SELECT CASE WHEN tt.bill_date::integer >= EXTRACT(MONTH FROM CURRENT_DATE) THEN EXTRACT(MONTH FROM CURRENT_DATE) ELSE EXTRACT(MONTH FROM CURRENT_DATE)-1 END FROM credit_account tt where tt.acct=t.credit_acct)", AiPushLf::getBillMonth);
        mpjLambdaWrapperLf.selectAs("(select cab.unsettled_bill_amt+cab.settled_bill_amt+cab.unamort_prin from credit_account_balance cab where cab.acct=t.credit_acct)", AiPushLf::getOverBal);
        mpjLambdaWrapperLf.eq(CreditAccount::getAcctType, "70");
        mpjLambdaWrapperLf.eq(CreditAccount::getMthsOdue, 1);
        mpjLambdaWrapperLf.gt(CreditAccountBalance::getSettledBillAmt, 0);
        mpjLambdaWrapperLf.eq(ConCustomer::getIsurgecust, "0");

        List<AiPushLf> listLf = selectJoinList(AiPushLf.class, mpjLambdaWrapperLf);

        System.out.println("listGr:" + listGr.size());
        System.out.println("listLf:" + listLf.size());
        XxlJobHelper.log("aiPush, 符合条件的账户类型,个人listGr:{} --->> 乐分listLf:{}", listGr.size(), listLf.size());

        List<AiPushLf> listMax = listGr.size() > listLf.size() ? listGr : listLf;
        List<AiPushLf> listMin = listGr.size() > listLf.size() ? listLf : listGr;
        List<AiPushLf> listArr = new ArrayList<>();


        listMax.forEach(x -> {
            listMin.forEach(i -> {
                if (Objects.equals(x.getAcctType(), "10") && Objects.equals(x.getCustomernumber(), i.getCustomernumber())) {    // 个人:10 乐分:70
                    System.out.println("检测到重复custid:" + x.getCustomernumber() + " " + i.getCustomernumber());
                    AiPushLf aiPushLf = new AiPushLf();
                    aiPushLf.setDataId(x.getDataId());
                    aiPushLf.setAcctType(x.getAcctType());
                    aiPushLf.setCustname(x.getCustname());
                    aiPushLf.setGender(x.getGender());
                    aiPushLf.setCustomernumber(x.getCustomernumber());
                    aiPushLf.setMobileNum(x.getMobileNum());
                    aiPushLf.setCardNo(x.getCardNo());
                    aiPushLf.setMthsOdue(x.getMthsOdue());
                    aiPushLf.setBillDate(x.getBillDate());
                    aiPushLf.setBillMonth(x.getBillMonth());
                    aiPushLf.setOverBal(x.getOverBal());
                    aiPushLf.setAge1Age6(x.getAge1Age6());
                    aiPushLf.setLowestRepayBal(x.getLowestRepayBal());
                    aiPushLf.setPaymtClrd(x.getPaymtClrd());
                    aiPushLf.setSettledBillAmt(x.getSettledBillAmt());
                    aiPushLf.setSettledBillInt(x.getSettledBillInt());
                    aiPushLf.setSettledBillFee(x.getSettledBillFee());
                    aiPushLf.setSettledBillPrin(x.getSettledBillPrin());
                    aiPushLf.setOpenDt(x.getOpenDt());
                    aiPushLf.setStmBalnce(x.getStmBalnce());

                    aiPushLf.setCardNoLf(i.getCardNo());
                    aiPushLf.setMthsOdueLf(i.getMthsOdue());
                    aiPushLf.setBillDateLf(i.getBillDate());
                    aiPushLf.setBillMonthLf(i.getBillMonth());
                    aiPushLf.setOverBalLf(i.getOverBal());
                    aiPushLf.setAge1Age6Lf(i.getAge1Age6());
                    aiPushLf.setLowestRepayBalLf(i.getLowestRepayBal());
                    aiPushLf.setPaymtClrdLf(i.getPaymtClrd());
                    aiPushLf.setSettledBillAmtLf(i.getSettledBillAmt());
                    aiPushLf.setSettledBillIntLf(i.getSettledBillInt());
                    aiPushLf.setSettledBillFeeLf(i.getSettledBillFee());
                    aiPushLf.setSettledBillPrinLf(i.getSettledBillPrin());
                    aiPushLf.setOpenDtLf(i.getOpenDt());
                    aiPushLf.setStmBalnceLf(i.getStmBalnce());
                    aiPushLf.setIsurgecust(i.getIsurgecust());
                    aiPushLf.setDataDt(i.getDataDt());
                    listArr.add(aiPushLf);
                }
                if (Objects.equals(x.getAcctType(), "70") && Objects.equals(x.getCustomernumber(), i.getCustomernumber())) {
                    AiPushLf aiPushLf = new AiPushLf();
                    aiPushLf.setDataId(i.getDataId());
                    aiPushLf.setAcctType(i.getAcctType());
                    aiPushLf.setCustname(i.getCustname());
                    aiPushLf.setGender(i.getGender());
                    aiPushLf.setCustomernumber(i.getCustomernumber());
                    aiPushLf.setMobileNum(i.getMobileNum());
                    aiPushLf.setCardNo(i.getCardNo());
                    aiPushLf.setMthsOdue(i.getMthsOdue());
                    aiPushLf.setBillDate(i.getBillDate());
                    aiPushLf.setBillMonth(i.getBillMonth());
                    aiPushLf.setOverBal(i.getOverBal());
                    aiPushLf.setAge1Age6(i.getAge1Age6());
                    aiPushLf.setLowestRepayBal(i.getLowestRepayBal());
                    aiPushLf.setPaymtClrd(i.getPaymtClrd());
                    aiPushLf.setSettledBillAmt(i.getSettledBillAmt());
                    aiPushLf.setSettledBillInt(i.getSettledBillInt());
                    aiPushLf.setSettledBillFee(i.getSettledBillFee());
                    aiPushLf.setSettledBillPrin(i.getSettledBillPrin());
                    aiPushLf.setOpenDt(i.getOpenDt());
                    aiPushLf.setStmBalnce(i.getStmBalnce());

                    aiPushLf.setCardNoLf(x.getCardNo());
                    aiPushLf.setMthsOdueLf(x.getMthsOdue());
                    aiPushLf.setBillDateLf(x.getBillDate());
                    aiPushLf.setBillMonthLf(x.getBillMonth());
                    aiPushLf.setOverBalLf(x.getOverBal());
                    aiPushLf.setAge1Age6Lf(x.getAge1Age6());
                    aiPushLf.setLowestRepayBalLf(x.getLowestRepayBal());
                    aiPushLf.setPaymtClrdLf(x.getPaymtClrd());
                    aiPushLf.setSettledBillAmtLf(x.getSettledBillAmt());
                    aiPushLf.setSettledBillIntLf(x.getSettledBillInt());
                    aiPushLf.setSettledBillFeeLf(x.getSettledBillFee());
                    aiPushLf.setSettledBillPrinLf(x.getSettledBillPrin());
                    aiPushLf.setOpenDtLf(x.getOpenDt());
                    aiPushLf.setStmBalnceLf(x.getStmBalnce());
                    aiPushLf.setIsurgecust(x.getIsurgecust());
                    aiPushLf.setDataDt(x.getDataDt());
                    listArr.add(aiPushLf);
                }
            });

            if (Objects.equals(x.getAcctType(), "10")) {
                AiPushLf aiPushLf = new AiPushLf();
                aiPushLf.setDataId(x.getDataId());
                aiPushLf.setAcctType(x.getAcctType());
                aiPushLf.setCustname(x.getCustname());
                aiPushLf.setGender(x.getGender());
                aiPushLf.setCustomernumber(x.getCustomernumber());
                aiPushLf.setMobileNum(x.getMobileNum());
                aiPushLf.setCardNo(x.getCardNo());
                aiPushLf.setMthsOdue(x.getMthsOdue());
                aiPushLf.setBillDate(x.getBillDate());
                aiPushLf.setBillMonth(x.getBillMonth());
                aiPushLf.setOverBal(x.getOverBal());
                aiPushLf.setAge1Age6(x.getAge1Age6());
                aiPushLf.setLowestRepayBal(x.getLowestRepayBal());
                aiPushLf.setPaymtClrd(x.getPaymtClrd());
                aiPushLf.setSettledBillAmt(x.getSettledBillAmt());
                aiPushLf.setSettledBillInt(x.getSettledBillInt());
                aiPushLf.setSettledBillFee(x.getSettledBillFee());
                aiPushLf.setSettledBillPrin(x.getSettledBillPrin());
                aiPushLf.setOpenDt(x.getOpenDt());
                aiPushLf.setStmBalnce(x.getStmBalnce());
                aiPushLf.setIsurgecust(x.getIsurgecust());
                aiPushLf.setDataDt(x.getDataDt());
                listArr.add(aiPushLf);
            }
            if (Objects.equals(x.getAcctType(), "70")) {
                AiPushLf aiPushLf = new AiPushLf();
                aiPushLf.setDataId(x.getDataId());
                aiPushLf.setAcctType(x.getAcctType());
                aiPushLf.setCustname(x.getCustname());
                aiPushLf.setGender(x.getGender());
                aiPushLf.setCustomernumber(x.getCustomernumber());
                aiPushLf.setMobileNum(x.getMobileNum());
                aiPushLf.setCardNoLf(x.getCardNo());
                aiPushLf.setMthsOdueLf(x.getMthsOdue());
                aiPushLf.setBillDateLf(x.getBillDate());
                aiPushLf.setBillMonthLf(x.getBillMonth());
                aiPushLf.setOverBalLf(x.getOverBal());
                aiPushLf.setAge1Age6Lf(x.getAge1Age6());
                aiPushLf.setLowestRepayBalLf(x.getLowestRepayBal());
                aiPushLf.setPaymtClrdLf(x.getPaymtClrd());
                aiPushLf.setSettledBillAmtLf(x.getSettledBillAmt());
                aiPushLf.setSettledBillIntLf(x.getSettledBillInt());
                aiPushLf.setSettledBillFeeLf(x.getSettledBillFee());
                aiPushLf.setSettledBillPrinLf(x.getSettledBillPrin());
                aiPushLf.setOpenDtLf(x.getOpenDt());
                aiPushLf.setStmBalnceLf(x.getStmBalnce());
                aiPushLf.setIsurgecust(x.getIsurgecust());
                aiPushLf.setDataDt(x.getDataDt());
                listArr.add(aiPushLf);
            }
        });

        System.out.println("初次:" + listArr.size());
        XxlJobHelper.log("初次:" + listArr.size());

        // 去重
        List<AiPushLf> listAll = removeDuplicatesUsingStream(listArr);
        System.out.println("去重后:" + listAll.size());
        XxlJobHelper.log("去重后:" + listAll.size());

        // 排除已合并报文
        List<AiPushLf> extraList = findUniqueInB(listAll, listMin);
        System.out.println("剩余待添加:" + extraList.size());
        XxlJobHelper.log("剩余待添加:" + extraList.size());

        // 最终条数
        extraList.forEach(x -> {
            if (Objects.equals(x.getAcctType(), "10")) {
                AiPushLf aiPushLf = new AiPushLf();
                aiPushLf.setDataId(x.getDataId());
                aiPushLf.setAcctType(x.getAcctType());
                aiPushLf.setCustname(x.getCustname());
                aiPushLf.setGender(x.getGender());
                aiPushLf.setCustomernumber(x.getCustomernumber());
                aiPushLf.setMobileNum(x.getMobileNum());
                aiPushLf.setCardNo(x.getCardNo());
                aiPushLf.setMthsOdue(x.getMthsOdue());
                aiPushLf.setBillDate(x.getBillDate());
                aiPushLf.setBillMonth(x.getBillMonth());
                aiPushLf.setOverBal(x.getOverBal());
                aiPushLf.setAge1Age6(x.getAge1Age6());
                aiPushLf.setLowestRepayBal(x.getLowestRepayBal());
                aiPushLf.setPaymtClrd(x.getPaymtClrd());
                aiPushLf.setSettledBillAmt(x.getSettledBillAmt());
                aiPushLf.setSettledBillInt(x.getSettledBillInt());
                aiPushLf.setSettledBillFee(x.getSettledBillFee());
                aiPushLf.setSettledBillPrin(x.getSettledBillPrin());
                aiPushLf.setOpenDt(x.getOpenDt());
                aiPushLf.setStmBalnce(x.getStmBalnce());
                aiPushLf.setIsurgecust(x.getIsurgecust());
                aiPushLf.setDataDt(x.getDataDt());
                listAll.add(aiPushLf);
            }
            if (Objects.equals(x.getAcctType(), "70")) {
                AiPushLf aiPushLf = new AiPushLf();
                aiPushLf.setDataId(x.getDataId());
                aiPushLf.setAcctType(x.getAcctType());
                aiPushLf.setCustname(x.getCustname());
                aiPushLf.setGender(x.getGender());
                aiPushLf.setCustomernumber(x.getCustomernumber());
                aiPushLf.setMobileNum(x.getMobileNum());
                aiPushLf.setCardNoLf(x.getCardNo());
                aiPushLf.setMthsOdueLf(x.getMthsOdue());
                aiPushLf.setBillDateLf(x.getBillDate());
                aiPushLf.setBillMonthLf(x.getBillMonth());
                aiPushLf.setOverBalLf(x.getOverBal());
                aiPushLf.setAge1Age6Lf(x.getAge1Age6());
                aiPushLf.setLowestRepayBalLf(x.getLowestRepayBal());
                aiPushLf.setPaymtClrdLf(x.getPaymtClrd());
                aiPushLf.setSettledBillAmtLf(x.getSettledBillAmt());
                aiPushLf.setSettledBillIntLf(x.getSettledBillInt());
                aiPushLf.setSettledBillFeeLf(x.getSettledBillFee());
                aiPushLf.setSettledBillPrinLf(x.getSettledBillPrin());
                aiPushLf.setOpenDtLf(x.getOpenDt());
                aiPushLf.setStmBalnceLf(x.getStmBalnce());
                aiPushLf.setIsurgecust(x.getIsurgecust());
                aiPushLf.setDataDt(x.getDataDt());
                listAll.add(aiPushLf);
            }
        });
        System.out.println("最终:" + listAll.size());
        XxlJobHelper.log("最终:" + extraList.size());

        // 使用Stream API转换每个对象的字段为字符串
        List<String> formattedStrings = listAll.stream()
                .map(mt -> mt.getDataId() + "|" + mt.getAcctType() + "|" + mt.getCustname() + "|" + mt.getGender() + "|" + mt.getCustomernumber() + "|" + mt.getMobileNum() + "|" + mt.getCardNo() + "|" + mt.getMthsOdue() + "|" + mt.getBillDate() + "|" + mt.getBillMonth() + "|" + mt.getOverBal() + "|" + mt.getAge1Age6() + "|" + mt.getLowestRepayBal() + "|" + mt.getPaymtClrd() + "|" + mt.getSettledBillAmt() + "|" + mt.getSettledBillInt() + "|" + mt.getSettledBillFee() + "|" + mt.getSettledBillPrin() + "|" + mt.getOpenDt() + "|" + mt.getStmBalnce()
                        + "|" + mt.getCardNoLf() + "|" + mt.getMthsOdueLf() + "|" + mt.getBillDateLf() + "|" + mt.getBillMonthLf() + "|" + mt.getOverBalLf() + "|" + mt.getAge1Age6Lf() + "|" + mt.getLowestRepayBalLf() + "|" + mt.getPaymtClrdLf() + "|" + mt.getSettledBillAmtLf() + "|" + mt.getSettledBillIntLf() + "|" + mt.getSettledBillFeeLf() + "|" + mt.getSettledBillPrinLf() + "|" + mt.getOpenDtLf() + "|" + mt.getStmBalnceLf() + "|" + mt.getIsurgecust() + "|" + mt.getDataDt())
                .collect(Collectors.toList());

        JSONObject bodyObject = new JSONObject();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("busiType", "144");

        // 将 List 转换为 JSONArray
        JSONArray jsonArray = (JSONArray) JSONArray.toJSON(formattedStrings);
        jsonObject.put("content", jsonArray);
        bodyObject.put("body", jsonObject);
        bodyObject.put("appCode", "D1002T");

        String httpBody = bodyObject.toJSONString();
        System.out.println("个人/乐分:httpBody:" + httpBody);
        XxlJobHelper.log("aiPush, 个人/乐分:httpBody:" + httpBody);

        sendAiPush(httpBody);
    }

    private void mTcd() {
        MPJLambdaWrapper<FiCreditcases> mpjLambdaWrapper = new MPJLambdaWrapper<>();
        mpjLambdaWrapper.leftJoin(CreditAccount.class, "c", CreditAccount::getAcct, FiCreditcases::getCreditAcct);
        mpjLambdaWrapper.leftJoin(CreditAccountBalance.class, "cb", CreditAccountBalance::getAcct, FiCreditcases::getCreditAcct);
        mpjLambdaWrapper.leftJoin(ConCustomer.class, "ct", ConCustomer::getCustomernumber, FiCreditcases::getCustomernumber);
        mpjLambdaWrapper.select(CreditAccount::getAcctType, CreditAccount::getMobileNum, CreditAccount::getMthsOdue, CreditAccount::getBillDate);
        mpjLambdaWrapper.select(CreditAccountBalance::getAge1Age6, CreditAccountBalance::getLowestRepayBal, CreditAccountBalance::getPaymtClrd, CreditAccountBalance::getSettledBillAmt, CreditAccountBalance::getSettledBillInt, CreditAccountBalance::getSettledBillFee, CreditAccountBalance::getSettledBillPrin, CreditAccountBalance::getStmBalnce);
        mpjLambdaWrapper.select(ConCustomer::getCustname, ConCustomer::getGender, ConCustomer::getCustomernumber, ConCustomer::getIsurgecust);
        //mpjLambdaWrapper.selectAs("t.creditcaseid", AiPushMt::getDataId);
        mpjLambdaWrapper.selectAs("SELECT concat(to_char(now(),'YYYYMMDDHH24MISS'),(1000 + floor(random() * 9000)::int))", AiPushLf::getDataId);
        mpjLambdaWrapper.selectAs("(select cd.card_no from credit_card cd where cd.acct=t.credit_acct LIMIT 1)", AiPushMt::getCardNo);
        mpjLambdaWrapper.selectAs("to_char(c.open_dt,'YYYY-MM-DD')", AiPushLf::getOpenDt);
        mpjLambdaWrapper.selectAs("fc_getbillmonth(cd.bill_date)", AiPushLf::getBillMonth);
        mpjLambdaWrapper.selectAs("to_char(t.crdt,'YYYYMMDD')", AiPushLf::getDataDt);
        //mpjLambdaWrapper.selectAs("(select case tt.bill_date when tt.bill_date >= DATE_FORMAT(CURDATE(),'%m') then DATE_FORMAT(CURDATE(),'%m') else DATE_FORMAT(CURDATE(),'%m')-1 end from credit_account tt where tt.acct=t.credit_acct)", AiPushMt::getBillMonth);
        //mpjLambdaWrapper.selectAs("(SELECT CASE WHEN tt.bill_date::integer >= EXTRACT(MONTH FROM CURRENT_DATE) THEN EXTRACT(MONTH FROM CURRENT_DATE) ELSE EXTRACT(MONTH FROM CURRENT_DATE)-1 END FROM credit_account tt where tt.acct=t.credit_acct)", AiPushLf::getBillMonth);
        mpjLambdaWrapper.selectAs("(select cab.unsettled_bill_amt+cab.settled_bill_amt+cab.unamort_prin from credit_account_balance cab where cab.acct=t.credit_acct)", AiPushMt::getOverBal);
        mpjLambdaWrapper.in(CreditAccount::getAcctType, "0", "42");
        mpjLambdaWrapper.eq(CreditAccount::getMthsOdue, 1);
        mpjLambdaWrapper.gt(CreditAccountBalance::getSettledBillAmt, 0);
        mpjLambdaWrapper.eq(ConCustomer::getIsurgecust, "0");

        List<AiPushMt> list = selectJoinList(AiPushMt.class, mpjLambdaWrapper);
        XxlJobHelper.log("aiPush, 符合条件的账户类型, 美团·车贷" + list.size() + "条.");
        System.out.println("list:" + list.size());

        // 使用Stream API转换每个对象的字段为字符串
        List<String> formattedStrings = list.stream()
                .map(mt -> mt.getDataId() + "|" + mt.getAcctType() + "|" + mt.getCustname() + "|" + mt.getGender() + "|" + mt.getCustomernumber() + "|" + mt.getMobileNum() + "|" + mt.getCardNo() + "|" + mt.getMthsOdue() + "|" + mt.getBillDate() + "|" + mt.getBillMonth() + "|" + mt.getOverBal() + "|" + mt.getAge1Age6() + "|" + mt.getLowestRepayBal() + "|" + mt.getPaymtClrd() + "|" + mt.getSettledBillAmt() + "|" + mt.getSettledBillInt() + "|" + mt.getSettledBillFee() + "|" + mt.getSettledBillPrin() + "|" + mt.getOpenDt() + "|" + mt.getStmBalnce() + "|" + mt.getIsurgecust() + "|" + mt.getDataDt())
                .collect(Collectors.toList());

        JSONObject bodyObject = new JSONObject();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("busiType", "145");

        // 将 List 转换为 JSONArray
        JSONArray jsonArray = (JSONArray) JSONArray.toJSON(formattedStrings);
        jsonObject.put("content", jsonArray);
        bodyObject.put("body", jsonObject);
        bodyObject.put("appCode", "D1002T");

        String httpBody = bodyObject.toJSONString();
        System.out.println("美团/车贷-httpBody:" + httpBody);
        XxlJobHelper.log("aiPush, 美团/车贷:httpBody:" + httpBody);

        sendAiPush(httpBody);
    }

    private void sendAiPush(String httpBody) {
        XxlJobHelper.log("XXL-JOB-sendAiPush, 进入接口调用");
        try {
            // 发送 POST 请求
            HttpResponse<JsonNode> jsonResponse = Unirest.post(aiurl)
                    .header("Content-Type", "application/json")
                    .body(httpBody)
                    .asJson();

            // 获取响应体
            int status = jsonResponse.getStatus();
            JsonNode responseBody = jsonResponse.getBody();

            // success
            XxlJobHelper.log("XXL-JOB-sendAiPush, AI推送接口结束.status：{} -->> res：{}", status, responseBody);
        } catch (Exception e) {
            // 输出错误日志
            XxlJobHelper.log("XXL-JOB-sendAiPush, 输出错误日志: " + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    private List<AiPushLf> removeDuplicatesUsingStream(List<AiPushLf> list) {
        return new ArrayList<>(list.stream()
                .collect(Collectors.toMap(
                        AiPushLf::getDataId, // key is the dataId
                        item -> item,       // value is the AiPushLf object
                        (existing, replacement) -> existing // in case of key collision, keep the existing
                ))
                .values());
    }

    private List<AiPushLf> findUniqueInB(List<AiPushLf> a, List<AiPushLf> b) {
        Set<Integer> dataIdsInA = new HashSet<>();
        Set<Integer> uniqueDataIdsInB = new HashSet<>();
        List<AiPushLf> result = new ArrayList<>();

        // 收集a中的dataId
        for (AiPushLf item : a) {
            dataIdsInA.add(Integer.parseInt(item.getCustomernumber()));
        }

        // 检查b中的项，确保它们不在a中，并且b中没有重复
        for (AiPushLf item : b) {
            int dataId = Integer.parseInt(item.getCustomernumber());
            if (!dataIdsInA.contains(dataId) && uniqueDataIdsInB.add(dataId)) {
                result.add(item);
            }
        }
        return result;
    }

}
